#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/time.h>
#include <time.h>

#include "GenericServer.h"
#include "tree.h"

#define HEADER_SIZE 4           /*  header is int of the size   */
#define EXP_SIZE 4
#define PORT 7


typedef struct Application
{
    Tree*       tree    ;
    GenServer*  server  ;
}Application;

typedef struct Client_t
{
    GSKey key;
}Client;

int ClientLess(void* _a, void* _b)
{
    return ((Client*)_a)->key < ((Client*)_b)->key;
}

 int TestFunc(void* _data)
 {
     printf("I am alive\n");

     return 0;
 }

int TestFunc1(void* _data)
{
    printf("I am alive22\n");

    return 0;
}


Application* ApplicationCreate(void)
{
    Application* app = (Application*)malloc(sizeof(Application));   /*  Allocate application    */

    app->tree = TreeNew(ClientLess);

    return app;
}

size_t HeaderCalcFuncApp(void* _app, void* _header)
{
    return *(int*)(_header);
}

void NewClientFuncApp(void* _app, GSKey _key)
{
    Client* client = (Client*)malloc(sizeof(Client));

    client->key = _key;
    puts("New Client arrived");

    TreeInsert(((Application*)_app)->tree, client);

}


void NewMssgFuncApp(void* _app, GSKey _key, void* _buffer, size_t _size)
{
    char recvBuf[255];
    char sendBuf[255];

    memcpy(recvBuf, _buffer, _size);
    recvBuf[_size] = '\0';
    printf("%s\n", recvBuf);

    if(!strcmp(recvBuf, "exit"))
    {
        puts("Getting out");
        GenServerStop(((Application*)_app)->server);
        return;
    }

    if(!strcmp(recvBuf, "virus"))
    {
        puts("Throwing out");
        GenServerDrop(((Application*)_app)->server, _key);
        return;
    }

    *(int*)sendBuf = strlen("HelloWorld");
    strcpy(sendBuf + HEADER_SIZE , "HelloWorld");
    GenServerWrite(((Application*)_app)->server, _key, sendBuf, strlen("HelloWorld") + HEADER_SIZE);
    *(int*)sendBuf = strlen("SecondTry");
    strcpy(sendBuf + HEADER_SIZE , "SecondTry");
    GenServerWrite(((Application*)_app)->server, _key, sendBuf, strlen("SecondTry") + HEADER_SIZE);
}



void NewExpFuncApp(void* _app, GSKey _key, void* _buffer, size_t _size)
{
    *((char*)_buffer + EXP_SIZE) = '\0';
    printf("%s\n", (char*)_buffer + sizeof(int));
}


void DisconnectFuncApp(void* _app, GSKey _key, size_t _nonRecvBytes, size_t _nonSendBytes)
{
    Client client;
    client.key = _key;
    printf("The number %d client is disconnect\nsent but not readen: %d bytes\nnot written %d bytes\n", (unsigned int)_key, _nonRecvBytes, _nonSendBytes);

    TreeRemove(((Application*)_app)->tree, TreeFind(((Application*)_app)->tree, &client));
}


int main()
{
    Application* app = ApplicationCreate();

    app->server = GenServerNew(PORT, app, HEADER_SIZE, HeaderCalcFuncApp, NewClientFuncApp, NewMssgFuncApp, EXP_SIZE, NewExpFuncApp, DisconnectFuncApp);

    GenServerSchedAddTask(app->server, TestFunc, 10000, 0);
    GenServerSchedAddTask(app->server, TestFunc1, 5000, 0);
    GenServerRun(app->server);

    GenServerDel(app->server);

    return 0;
}
